package conn

import (
	"gitee.com/cooge/impush/core"
	"gitee.com/cooge/impush/message"
	"gitee.com/cooge/impush/stream"
	"gitee.com/cooge/impush/user"
	"gitee.com/cooge/impush/util"
	log "github.com/sirupsen/logrus"
	"net"
	"strconv"
	"time"
	"sync"
)

type XTcpConn struct {
	*user.UserLite
	ms *stream.MessageStream
	closeOnce sync.Once
}

func NewXTcpConn(conn *net.TCPConn) *XTcpConn {
	return &XTcpConn{UserLite: user.NewUserLite(conn, 30000, "", util.GetNowTime(),message.TCP,true), ms: stream.NewMessageStream(conn)}
}
func (tcp *XTcpConn) Start() {
	go tcp.start()
}

func (tcp *XTcpConn) SendMessage(msg *message.Message) (int, error) {
	bs := msg.MessageToByte()
	return tcp.Write(bs)
}
func (tcp *XTcpConn) SetReadDeadline() {
	tcp.UserTCPConn.SetReadDeadline(time.Now().Add(time.Duration(tcp.LiveTime) * time.Millisecond))
}
func (tcp *XTcpConn) Close(userId string) error {
	tcp.closeOnce.Do(func(){
		core.DeleteUser(userId, tcp)
		tcp.UserTCPConn.Close()
	})
	return nil
}

func (tcp *XTcpConn) start() {
	tcp.Write(message.StartLogin())
	for {
		mg, err := tcp.ms.ReadMessage()
		if err != nil {
			break
		} else {
			tcp.handle(mg)
		}
	}
	log.Debug(tcp.UserId, "连接断开")
	tcp.Close(tcp.UserId)
}
func (tcp *XTcpConn) handle(msg *message.Message) {
	type_ := msg.Heads.Get(message.TYPE)
	switch type_ {
	case message.LOGIN:
		{
			usarename := msg.Heads.Get(message.USERNAME)
			if len(usarename) > 0 {
				time_ := msg.Heads.Get(message.TIME)
				if len(time_) > 0 {
					ti, err := strconv.Atoi(time_)
					if err == nil {
						tcp.LiveTime = ti + tcp.LiveTime
					} else {
						log.Debug("获取心跳时间失败", err)
					}
				}
			}
			core.AddUser(usarename, tcp)
			tcp.UserId = usarename
			tcp.Write(message.LoginSuccess())
		}
	case message.MESSAGE:
		{
			touser := msg.Heads.Get(message.TO)
			msg.Heads[message.FROM] = tcp.UserId
			_, err := core.SendMessage(touser, msg)
			if err == nil {
				tcp.SendMessage(message.SendSuccess(msg.Heads[message.MESSAGE_ID]))
			} else {
				tcp.SendMessage(message.SendFail(msg.Heads[message.MESSAGE_ID]))
			}
		}
	case message.LIVE:
		{
			tcp.Write(message.Live())
		}
	}
	tcp.SetReadDeadline()
}
